//TODO: 
//  move String -> vec[u8]?
//  create skiplist db

use crate::db::Error;

use std::collections::BTreeMap;


pub struct BTreeMapDB {
    db: BTreeMap<String, String>
}

impl BTreeMapDB {
    pub fn new() -> Self {
        BTreeMapDB{ db: BTreeMap::new()}
    }

    pub fn put(&mut self, key: String, value: String) -> Result<bool, Error> {
        self.db.insert(key, value);
        Ok(true)
    }

    pub fn delete(&mut self, key: &str) -> Result<bool, Error> {
        match self.db.remove(key) {
            None => {
                return Err(Error::KeyNotExist);
            },
            Some(_) => {
                return Ok(true)
            }
        }
    }
    pub fn get(&self, key: &str) -> Result<&str, Error> {
        match self.db.get(key) {
            None => {
                return Err(Error::KeyNotExist);
            },
            Some(ref v) => {
                return Ok(v);
            }
        }
    }

    pub fn iter(&self) -> Iter {
        Iter::new(self.db.iter())
    }
    pub fn iter_mut(&mut self) -> IterMut {
        IterMut::new(self.db.iter_mut())
    }
}

impl Drop for BTreeMapDB {
    fn drop(self: &mut Self){
        println!("btree map db droped");
    }
}
impl Default for BTreeMapDB {
    fn default() -> Self{
        BTreeMapDB::new()
    }
}


pub struct Iter<'a> {
    iter: std::collections::btree_map::Iter<'a, String, String>,
}
impl <'a> Iter<'a> {
    fn new(iter: std::collections::btree_map::Iter<'a, String, String>) -> Self {
        Iter{iter}
    }
}
impl <'a> Iterator for Iter<'a> {
    type Item = (&'a String, &'a String);
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }
}


pub struct IterMut<'a> {
    iter: std::collections::btree_map::IterMut<'a, String, String>,
}
impl <'a> IterMut<'a> {
    fn new(iter: std::collections::btree_map::IterMut<'a, String, String>) -> Self{
        Self { iter }
    }
}
impl <'a> Iterator for IterMut<'a> {
    type Item = (&'a String, &'a mut String);
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn db(){
        let mut db = BTreeMapDB::new();
        //put & delete ok
        db.put("key".to_string(), "value".to_string()).unwrap();
        db.delete("key").unwrap();
        assert_eq!(Error::KeyNotExist, db.delete("key").unwrap_err());

        //put & get ok
        db.put("key".to_string(), "value".to_string()).unwrap();
        assert_eq!("value", db.get("key").unwrap());
    }

    #[test]
    fn get_key_not_exist(){
        let db = BTreeMapDB::new();
        assert_eq!(Error::KeyNotExist, db.get("key").unwrap_err());
    }
    #[test]
    fn delete_key_not_exist(){
        let mut db = BTreeMapDB::new();
        assert_eq!(Error::KeyNotExist, db.delete("key").unwrap_err());
    }
    #[test]
    fn put_duplicated_key(){
        let mut db = BTreeMapDB::new();
        let key = "key";
        let value = "value";
        db.put(key.to_string(), value.to_string()).unwrap();
        assert_eq!(value, db.get(key).unwrap());

        let last_value = "last_value";
        db.put(key.to_string(), last_value.to_string()).unwrap();
        assert_eq!(last_value, db.get(key).unwrap());
    }

    #[test]
    fn db_default(){
        let db = BTreeMapDB::default();
        db.get("key").unwrap_err();
    }
    #[test]
    fn iterator() {
        let db = BTreeMapDB::default();

        assert_eq!(0usize, db.iter().count());
        for (k, v) in db.iter() {
            println!("k:{}, v:{}", k, v);
        }
    }
    #[test]
    fn iter_mut() {
        let mut db = BTreeMapDB::default();

        assert_eq!(0usize, db.iter_mut().count());

        db.put("hello".to_string(), "world".to_string()).unwrap();


        for (k, v) in db.iter_mut() {
            println!("---k:{}, v:{}", k, v);
            *v = "owner".to_string();
            println!("k:{}, v:{}---", k, v);
        }
        assert_eq!("owner", db.get("hello").unwrap());

        assert_eq!(1usize, db.iter_mut().count());
    }
}

//TODO: customer Iterator ???
//TODO: use Cell(), RefCell((); 
//  1. differ ???  
//  2. Use case ????
//  3. Internal of Cell???
